﻿using log4net;
using log4net.Config;
using System;
using System.Data.Entity.Validation;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using Microsoft.ServiceBus.Messaging;
using System.Xml.Serialization;
using System.IO;
using Newtonsoft.Json;
using GrayParrot.Communications.Core;
using GrayParrot.Extensions.Strings;
using GrayParrot.Caching;
using GrayParrot.Infrastructure;
using GrayParrot.Configuration;
using GrayParrot.ServiceBus.Configuration;
using GrayParrot.ServiceBus;
using GrayParrot.Web.Security;
using GrayParrot.Communications.Configuration;
using GrayParrot.Web.Formly;
using GrayParrot.Core.Json;
using System.Globalization;
using GrayParrot.Core;
using Newtonsoft.Json.Linq;
//using ServiceBroker = GrayParrot.ServiceBroker.Configuration;

namespace ConsoleApplication1
{
    public class JavaScriptSettings
    {
        public Newtonsoft.Json.Linq.JRaw OnLoadFunction { get; set; }
        public Newtonsoft.Json.Linq.JRaw OnUnloadFunction { get; set; }
    }

    public class TestMsg : MessageBusBase<TestMsg>
    {
        public string Feed { get; set; }

        public TestMsg()
        {

        }
    }

    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    [DataContract(Namespace = "")]
    public class BufferRemoveMessage
    {
        /// <summary>
        /// Gets or sets the avvenimento.
        /// </summary>
        /// <value>
        /// The avvenimento.
        /// </value>
        [DataMember]
        public int Avvenimento { get; set; }
        /// <summary>
        /// Gets or sets the type of the group.
        /// </summary>
        /// <value>
        /// The type of the group.
        /// </value>
        [DataMember]
        public int GroupType { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether this instance is removable.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is removable; otherwise, <c>false</c>.
        /// </value>
        [DataMember]
        public bool IsRemovable { get; set; }
        /// <summary>
        /// Gets or sets the match identifier.
        /// </summary>
        /// <value>
        /// The match identifier.
        /// </value>
        [DataMember]
        public long MatchId { get; set; }
        /// <summary>
        /// Gets or sets the palinsesto.
        /// </summary>
        /// <value>
        /// The palinsesto.
        /// </value>
        [DataMember]
        public int Palinsesto { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="BufferRemoveMessage"/> class.
        /// </summary>
        public BufferRemoveMessage()
        {
        }
    }

    [Serializable]
    [DataContract(Namespace = "")]
    public class ServiceBusMessage<T> where T : class, new()
    {
        [DataMember]
        public T Body { get; set; }
        [DataMember]
        public Guid CorrelationID { get; set; }
        [DataMember]
        public Guid MessageID { get; set; }
        [DataMember]
        public string MessageName { get; set; }
        [DataMember]
        public DateTime Timestamp { get; set; }

        public ServiceBusMessage()
        {
            CorrelationID = Guid.NewGuid();
            MessageID = Guid.NewGuid();
            Timestamp = DateTime.Now;
            Body = new T();
        }

        public ServiceBusMessage(string messageName)
        {
            CorrelationID = Guid.NewGuid();
            MessageID = Guid.NewGuid();
            MessageName = messageName;
            Timestamp = DateTime.Now;
            Body = new T();
        }

        /// <summary>
        /// Convert To the ServiceBus BrokeredMessage object...
        /// </summary>
        /// <returns>a BrokeredMessage object if success, null otherwise</returns>
        public BrokeredMessage ToBrokeredMessage()
        {
            BrokeredMessage retValue = null;

            retValue = new BrokeredMessage(this);
            retValue.Properties["CorrelationID"] = this.CorrelationID;
            retValue.Properties["MessageName"] = this.MessageName;

            return retValue;
        }

        public BrokeredMessage ToBrokeredMessage(string xmlObject)
        {
            BrokeredMessage retValue = null;

            retValue = new BrokeredMessage(xmlObject);
            retValue.Properties["CorrelationID"] = this.CorrelationID;
            retValue.Properties["MessageName"] = this.MessageName;

            return retValue;
        }
    }

    [Serializable]
    [DataContract(Namespace = "")]
    public class TestDelayedMessage : MessageBusBase<TestDelayedMessage>
    {
        [DataMember]
        public int Palinsesto { get; set; }
        
        [DataMember]
        public int Avvenimento { get; set; }

        public TestDelayedMessage()
        {
        }
    }

    class Program
    {
        private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            //ReturnValue<long> pppp = ReturnValue<long>.WithDefault(false);
            //Console.WriteLine(pppp);

            TestDelayedMessageSettings();
    

            //TestFormly2();

            //TestExpressionPropertiesMetadata();

            //string m_user = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            //Console.WriteLine(m_user);

            //TestTraceActivity("pippo", 50);

            //TestServiceBrokerSend();

            //TestFormly();

            //TestEmailSettings();

            //TestTimeZone();

            //JavaScriptSettings settings = new JavaScriptSettings
            //{
            //    OnLoadFunction = new Newtonsoft.Json.Linq.JRaw("OnLoad"),
            //    OnUnloadFunction = new Newtonsoft.Json.Linq.JRaw("function(e) { alert(e); }")
            //};
            //string json = JsonConvert.SerializeObject(settings, Formatting.Indented);
            //Console.WriteLine(json);

            //TestCacheAttr(1, "2", 3);
            
            //JavaScriptSettings settings = new JavaScriptSettings
            //{
            //    OnLoadFunction = new Newtonsoft.Json.Linq.JRaw("OnLoad"),
            //    OnUnloadFunction = new Newtonsoft.Json.Linq.JRaw("function(e) { alert(e); }")
            //};
            //string json = JsonConvert.SerializeObject(settings, Formatting.Indented);
            //Console.WriteLine(json);

            ////TestCacheAttr(1, "2", 3);
            
            //int tot = Show<int>("", 3);

            //tot = Show<int>("", 3);

            //int tot2 = Show<double>("pippo", 3.5);

            //TestCache();
            //TestCache2();

            //string pppp = "1, 2";
            //string pppp1 = pppp.RemoveLast();
            //Console.WriteLine(pppp1);

            //TestSubcribers();

            //TestNotificaMessaggi();

            //TestPublisher();

            //TestConfiguration();

            //
            //bool ppp = GrayParrotSettings.GetConfiguration(@"GrayParrotGroup/GrayParrotSettings").UserNameWithoutDomain;
            //Console.WriteLine(ppp);


            //XmlConfigurator.Configure();

            //log4net.LogicalThreadContext.Properties["InputArguments"] = "ciao ciao";
            //log.Debug("Debug message");
        }

        private static void TestDelayedMessageSettings()
        {
            ReturnValue<bool> m_resValue = DelayedMessagesHelper.SaveDelayedMessageInfo(Guid.NewGuid(), DateTime.Now.AddDays(2));
            Console.WriteLine(m_resValue);



            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            GrayParrot.ServiceBus.Configuration.Subscription m_subs = GrayParrot.ServiceBus.Configuration.ServiceBusSettingsExtension.GetSubscription(pp, "TestDelayed");

            DateTime m_delay = DateTime.Now.AddMinutes(1);

            for (int i = 0; i < 2000; i++)
            {
                ServiceBusMessageBag<BufferRemoveMessage> m_msg = new ServiceBusMessageBag<BufferRemoveMessage>(m_subs.MessageName);
                m_msg.DelayedDate = m_delay;
                m_msg.IsDelayed = true;
                m_msg.Body = new BufferRemoveMessage() { Palinsesto = 10, Avvenimento = 1, IsRemovable = true, GroupType = 1, MatchId = 1001 };

                //
                using (Publisher p = new Publisher(m_subs))
                {
                    // si invia il messaggio come XML...
                    bool result = p.SendDelayedMessage(m_msg.ToXMLBrokeredMessage());
                }
            }

            //
            //BrokeredMessage msg = new BrokeredMessage();
            //ReturnValue<DelayedMessageStatus> m_res = msg.CheckDelayed();

            //Console.WriteLine(m_res);
        }

        [WithActivityLog(ConnectionString = "TradingToolAuth")]
        private static void TestTraceActivity(string name, int age)
        {
            Console.WriteLine("{0}, {1}", name, age);
        }

        //private static void TestServiceBrokerSend()
        //{
        //    ConfigurationManagerHelper pp = new ConfigurationManagerHelper();

        //    GrayParrot.ServiceBroker.Configuration.Subscription m_subs = ServiceBroker.ServiceBrokerSettingsExtension.GetSubscription(pp, "feeds"); // pp.GetSubscription("feeds");

        //    using (GrayParrot.ServiceBroker.Publisher m_p = new GrayParrot.ServiceBroker.Publisher(m_subs))
        //    {
        //        m_p.Send("ciao ciao");
        //    }
        //}

        private static void TestTimeZone()
        {
            string timeZone = " (ora legale Europa occidentale)";
            string data = "Thu Sep 01 2016 06:30:00 GMT+0200 (ora legale Europa occidentale)";

            data = data.Replace(timeZone, "");

            string format = "ddd MMM dd yyyy HH:mm:ss 'GMT'K";
            DateTime date;
            bool validFormat = DateTime.TryParseExact(data, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out date);
            Console.Write(validFormat ? date.ToString() : "Not a valid format");
        }

        private static void TestExpressionPropertiesMetadata()
        {
            var m_fields = FormlyHelper.ToFormly<TestExpressionPropertiesMetadata>(typeof(TestExpressionPropertiesMetadata));

            //m_fields.AddExpressionProperty("Quantita", new List<ExpressionProperty>() {
            //                                                           new ExpressionProperty("templateOptions.addonRight.class", "ProvaCallback"),
            //                                                           new ExpressionProperty("templateOptions.addonRight.class2", "ProvaCallback2")
            //                                                         });

            string retValue = FormlyHelper.Serialize(m_fields);

            //string m_retValue = retValue.Replace("rsFields", "fields");

            Console.WriteLine(retValue);
        }

        private static void TestFormly()
        {
            //var m_fields = FormlyHelper.ToFormly<MovimentiExMetadata>(typeof(MovimentiExMetadata));

            var m_fields = FormlyHelper.ToFormly<MovimentiDetailMetadata>(typeof(MovimentiDetailMetadata));

            //var m_fields = new FormlyFactory()
            //                   .AddSelect("selSport", "Sport", "", "Seleziona uno sport...", false, true, null, "/api/Common/LoadDisciplineSportRadar")
            //                   .AddRadio("radioTipologia", "Tipologia", "", "Indica se associare squadre o giocatori", false, true, "/api/elenchi/LoadTipologia")
            //                   .Create();

            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ContractResolver = new NullToEmptyListResolver();
            settings.Converters = new List<JsonConverter> { 
                new Newtonsoft.Json.Converters.StringEnumConverter { CamelCaseText = false }
            };
            settings.Formatting = Formatting.Indented;
            settings.NullValueHandling = NullValueHandling.Ignore;

            m_fields.Hide("Prenotata");

            string retValue = JsonConvert.SerializeObject(m_fields, settings);

            
            //string m_retValue = retValue.Replace("rsFields", "fields");


            Console.WriteLine(retValue);
        }

        private static void TestEmailSettings()
        {
            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            CommunicationsSettings m_commCfg = pp.GetCommunicationsSettings();

            string m_disposition = m_commCfg.EmailSettings.EmailDeliverySettings.DispositionNotificationTo;
            bool m_requireDeliveryReceipt = m_commCfg.EmailSettings.EmailDeliverySettings.RequireDeliverySuccessReceipt;
            bool m_requireReadReceipt = m_commCfg.EmailSettings.EmailDeliverySettings.RequireReadReceipt;

            Console.WriteLine("{0} Delivery:{1} Read:{2}", m_disposition, m_requireDeliveryReceipt, m_requireReadReceipt);
        }

        //[WithCache]
        private static int TestCacheAttr(int a, string b, double c)
        {
            int retValue = 10;

            return retValue;
        }

        [WithExceptionHandling]   // <-- catch anche degli errori eventuali negli attributi che seguono
        [WithCache]               // <-- eventuali errori in questo attributo vengono trappati in automatico
        public static int Show<T>(string msg, T value)
        {
            int retValue = 10;

            return retValue;
        }

        private static void TestCache()
        {
            /* auto-mapping cache type... */
            //ICache m_theCache = CacheHelper.Instance.GetCache();
            //m_theCache.Add<int>("T2", 102);
            //int p2 = m_theCache.Get<int>("T2");
            //Console.WriteLine(p2);

            /* manually create cache and use it... */
            GrayParrot.Caching.Cache m_cache = GrayParrot.Caching.Cache.Create();
            m_cache.Add<int>("T1", 10);
            m_cache.Update<int>("T1", 101);
            int p1 = m_cache.Get<int>("T1");
            Console.WriteLine(p1);
        }

        private static void TestCache2()
        {
            /* auto-mapping cache type... */
            ICache m_theCache = CacheHelper.Instance.GetCache();
            m_theCache.Add<int>("T2", 103);
            int p2 = m_theCache.Get<int>("T2");
            Console.WriteLine(p2);
        }

        private static void TestSubcribers()
        {
            TestSubscriber pp = new TestSubscriber();
            pp.Init();
        }

        private static void TestNotificaMessaggi()
        {
            GrayParrot.Communications.Notifications.Notification pp = new GrayParrot.Communications.Notifications.Notification();
            bool result = pp.WithSeverity(MessageSeverity.Info).OfType("ANNULLO").AsEmail().AsMessage().AsNotification().Send("esempio di comunicazione");

            Console.WriteLine(result);
        }

        private static void TestConfiguration()
        {
            ServiceBusSettings cfg = ServiceBusSettings.GetConfiguration(@"GrayParrotGroup/ServiceBusSettings");
            Endpoint m_endpoint = cfg.Endpoints["Test"];
            Subscription m_subs1 = m_endpoint.Subscriptions["feeds"];
            Console.WriteLine("Subscription:{0}\n Topic:{1}\n MessageName:{2}\n ReadDL:{3}\n", m_subs1.Name, m_subs1.Topic, m_subs1.MessageName, m_subs1.ReadDL);

            ServiceBusSettings cfg2 = ConfigurationManagerHelper.Get<ServiceBusSettings>(@"GrayParrotGroup/ServiceBusSettings");
            Endpoint m_endpoint1 = cfg.Endpoints["Test"];
            Subscription m_subs2 = m_endpoint.Subscriptions["feeds"];
            Console.WriteLine("Subscription:{0}\n Topic:{1}\n MessageName:{2}\n ReadDL:{3}\n", m_subs2.Name, m_subs2.Topic, m_subs2.MessageName, m_subs2.ReadDL);

            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            Subscription m_subs3 = pp.GetSubscription("Test", "feeds");
            Console.WriteLine("Subscription:{0}\n Topic:{1}\n MessageName:{2}\n ReadDL:{3}\n", m_subs3.Name, m_subs3.Topic, m_subs3.MessageName, m_subs3.ReadDL);
        }

        private static void TestPublisher()
        {
            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            Subscription m_subs = pp.GetSubscription("test", "odds_notification");

            string m_endPoint = ""; // m_subs.ConnectionString;
            string m_topic = m_subs.Topic;
            string m_messageName = m_subs.MessageName;

            using (Publisher oddsPublisher = new Publisher(m_endPoint, m_topic))
            {
                ServiceBusMessage<BufferRemoveMessage> m_msg = new ServiceBusMessage<BufferRemoveMessage>(m_messageName);
                m_msg.Body.MatchId = 10101;
                m_msg.Body.Palinsesto = 1;
                m_msg.Body.Avvenimento = 1;
                m_msg.Body.IsRemovable = true;
                m_msg.Body.GroupType = 1;


                var xml = SerializeAsXml(m_msg);
                var m_msgB = m_msg.ToBrokeredMessage(xml);

                /* funzionante */
                //TestMsg m_msg = new TestMsg();
                //m_msg.MessageName = m_messageName;
                //m_msg.MessageID = Guid.NewGuid();
                //m_msg.Timestamp = DateTime.Now;
                //m_msg.Feed = "ciao ciao";

                //var xml = SerializeAsXml(m_msg);
                ////var m_msgB = m_msg.ToBrokeredMessage();
                //var m_msgB = m_msg.ToBrokeredMessage(xml);
                /* funzionante */

                //Microsoft.ServiceBus.Messaging.BrokeredMessage retValue = new BrokeredMessage(m_msg); //"prova prova");
                //var ppppp = m_msg.ToBrokeredMessage();
                oddsPublisher.Send(m_msgB);
            }
        }

        private static string SerializeAsXml(object obj)
        {
            var type = obj.GetType();
            var xmlSerializer = new XmlSerializer(type);

            using (var memStream = new MemoryStream())
            {
                xmlSerializer.Serialize(memStream, obj);

                return Encoding.Default.GetString(memStream.ToArray());
            }
        }

        [WithExceptionHandling]
        private static void TestException(int uno, string due)
        {
            int a = 0;
            int b = 1;

            int c = 0;

            c = b / a;

        }

        private static void TestFormly2()
        {
            var m_fields = new FormlyFactory()
                               .AddInput("txtId", "Id", "", "", false, true, 0, 0, TextFieldBehaviors.Hidden)
                               .AddInput("txtPalinsesto", "Palinsesto", "", "inserisci il palinsesto", false, true, 0, 0)
                               .AddInput("txtAvvenimento", "Avvenimento", "", "inserisci l'avvenimento", false, true, 0, 0)
                               .Create();

            string retValue = FormlyHelper.Serialize(m_fields);

            Console.WriteLine(retValue);
        }
    }
}
